Crypto Infinite
[crypto]
Crypto Infinite
Crypto has been around forever. Does this challenge go on forever? Let us know in the comments below or find the flag to prove us wrong.
nc chal.tuctf.com 30102
Recon
from pwn import *
import sys
c = remote("chal.tuctf.com", 30102)
while True:
r = c.readuntil("\n")
if "Give me text:" in r:
c.send("abcdefghijklmnopqrstuvwxyz\n")
if "encrypted is" in r:
alpha = r.strip("\n").split(" ")[3:]
print "NEW ALPHA: " + repr(alpha)
if not r.startswith("Decrypt"):
print r
continue
print "LINE: " + r
p = r.strip("\n")[8:].split(" ")
o = ""
for v in p:
o += chr(0x41 + alpha.index(v))
print "GOT: " + o
c.send(o + "\n")
c.interactive()
L7 solution, breaks on L8
Level 5 is a polyalphabetic substitution for which every character has 8 different encodings, and they are chosen based on pos % 8
of the character in the plaintext.
Level 6 introduces a permutation, based on some formula which is based on the length of the plaintext.
Level 7 is nothing new...
from pwn import *
import sys
def permute(n):
perm = {}
rev = {}
perm[0], rev[0] = 0, 0
perm[1], rev[4] = 4, 1
start = 1
for i in range(2, n):
if perm[i-1] + 4 >= n:
perm[i] = start
rev[start] = i
start += 1
else:
perm[i] = perm[i-1] + 4
rev[perm[i]] = i
def p(s):
x = list(s)
for i, v in enumerate(s):
x[perm[i]] = s[i]
return x
def r(s):
x = list(s)
for i, v in enumerate(s):
x[rev[i]] = s[i]
return x
return p, r
def buildmap(alpha, encoded, n):
maps = {}
for i in range(0, n * int(len(alpha) // n), n):
for j in range(i, i+n):
key = (i + j) % n
if key not in maps:
maps[key] = {}
maps[key][encoded[j]] = alpha[j]
return maps
c = remote("chal.tuctf.com", 30102)
ABC = "abcdefghijklmnopqrstuvwxyz".upper()
alpha = ABC
levels = {
0: (1, False),
1: (1, False),
2: (1, False),
3: (1, False),
4: (1, False),
5: (8, False),
6: (1, True),
7: (1, False),
8: (1, False),
}
level = 0
while True:
r = c.readuntil("\n")
if r.startswith("Level"):
level = int(r.strip("\n").split(" ")[1])
lrep, permute = levels[level]
alpha = ''.join([str(i) * lrep for i in ABC])
if "Give me text:" in r:
c.send(alpha + "\n")
if "encrypted is" in r:
salpha = r.strip("\n").split(" ")[3:]
if permute:
salpha = permute(len(salpha))[0](salpha)
maps = buildmap(alpha, salpha, lrep)
print("LENGTHS: " + str(len(alpha)) + " " + str(len(salpha)))
print("ORIG: " + repr(alpha))
print("NEW ALPHA: " + repr(salpha))
if not r.startswith("Decrypt"):
print('< ' + r)
continue
print("LINE: " + r)
p = r.strip("\n")[8:].split(" ")
o = ""
for i, v in enumerate(p):
o += maps[(i % lrep)][v]
if permute:
o = ''.join(permute(len(o))[0](o))
print("GOT: " + repr(o))
c.send(o + "\n")
c.interactive()
Level 6 samples
A A A A
_| _| _| _|
B B B B
|_| |_| |_| |_|
A B C D A B C D
_| _| |_| |_| |_ |_ ] ]
X B U I X B U I
.> .> |_| |_| < < |- |-
Y B V J Y B V J
.< .< |_| |_| ^ ^ ._| ._|
Y B X J Y B X J
.< .< |_| |_| .> .> ._| ._|
Y B Y B Y B Y B
.< .< |_| |_| .< .< |_| |_|
A R
_| |.-
R A
|.- _|
A R R A
_| |.- |.- _|
A R R A A R R A A R R A A R R A
_| _| _| _| |.- |.- |.- |.- |.- |.- |.- |.- _| _| _| _|
A R A R A R A R A R A R A R A R
_| _| _| _| |.- |.- |.- |.- _| _| _| _| |.- |.- |.- |.-
C R C R C R C R C R C R C R C R
|_ |_ |_ |_ |.- |.- |.- |.- |_ |_ |_ |_ |.- |.- |.- |.-
Y R Y R Y R Y R Y R Y R Y R Y R
.< .< .< .< |.- |.- |.- |.- .< .< .< .< |.- |.- |.- |.-
Y B Y B Y B Y B Y B Y B Y B Y B
.< .< .< .< |_| |_| |_| |_| .< .< .< .< |_| |_| |_| |_|
Y B Y B Y B Y B Y B Y B Y B Y B Y B Y B
.< .< .< .< .< |_| |_| |_| |_| |_| .< .< .< .< .< |_| |_| |_| |_| |_|
Y Y Y Y Y B B B B B Y Y Y Y Y B B B B B
.< .< |_| .< |_| .< |_| |_| .< |_| .< |_| .< .< |_| .< |_| .< |_| |_|
Y Y B Y B Y B B Y B Y B Y Y B Y B Y B B
B A R R A C U D A
|_| _| _| _| |_ |.- < |.- ]
B X R A T M O A
|_| > .> .] |.- [. _| _|
B X R A T M O P
|_| > .> .] |.- [. _| .-|
B Y R A T M O P
|_| > .< .] |.- [. _| .-|
B S R A T M O P
|_| > v .] |.- [. _| .-|
B S R A Q M O P
|_| |.-| v .] |.- [. _| .-|
B S R T Q M O P
|_| |.-| v .] |.- [. > .-|
A = _|
B = |_|
S = v
R = |.-
P = .-|
T = >
X = .>
C = |_
M = .]
A B S R P T X C
A P B T S X R C
_| |_| v |.- .-| > .> |_ # MAPPED 1-1
_| .-| |_| > v .> |.- |_ # PERMUTED
0 -> 0
1 -> 2
2 -> 4
3 -> 6
4 -> 1
5 -> 3
6 -> 5
7 -> 7
* 2 then mod 7 for everything between beginning and end for anything larger than 3? Try with length == 9
0 1 2 3 4 5 6 7 8
A B S R P T X C X
_| |_| v |.- .-| > .> |_ .> # MAPPED 1-1
_| .-| .> |_| > v .> |.- |_ # PERMUTED
0 -> 0
1 -> 3
2 -> 5
3 -> 7
4 -> 1
5 -> 4
6 -> 6
7 -> 8
8 -> 2
Unsure of this one, try with M instead of X at the end:
0 1 2 3 4 5 6 7 8
A B S R P T X C M
A P M B T S X R C # PERMUTED
_| |_| v |.- .-| > .> |_ .] # MAPPED 1-1
_| .-| .] |_| > v .> |.- |_ # PERMUTED
0 -> 0
1 -> 3
2 -> 5
3 -> 7
4 -> 1
5 -> 4
6 -> 6
7 -> 8
8 -> 2
0 1 2 3 4
A B S R P
_| |_| v |.- .-| # MAPPED 1-1
_| .-| |_| v |.- # PERMUTED
0 -> 0
1 -> 2
2 -> 3
3 -> 4
4 -> 1
0 1 2 3 4 5
A B S R P T
_| |_| v |.- .-| > # MAPPED 1-1
_| .-| |_| > v |.- # PERMUTED
0 -> 0
1 -> 2
2 -> 4
3 -> 5
4 -> 1
5 -> 3
Looks like a permutation (on the indices), for strings of length \(n\) that works as: \(f(0) = 0\) \(f(x) = f(x - 1) + 2 \mod n\) if \(f(x - 1) + 2 \mod n\) has not yet been taken, else keep going by adding 1.
Maybe not..
Okay, permutations are the other way around:
A = _|
B = |_|
S = v
R = |.-
P = .-|
T = >
X = .>
C = |_
M = .]
Z = .^
0 1 2 3 4 5
A B S R P T
A P B T S R
_| |_| v |.- .-| > # MAPPED 1-1
_| .-| |_| > v |.- # PERMUTED
0 -> 0
1 -> 2
2 -> 4
3 -> 5
4 -> 1
5 -> 3
0 -> 0
1 -> 4
2 -> 1
3 -> 5
4 -> 2
5 -> 3
0 1 2 3 4 5 6 7 8 9
A B S R P T X C M Z
A P M B T Z S X R C
_| |_| v |.- .-| > .> |_ .] .^ # MAPPED 1-1
_| .-| .] |_| > .^ v .> |.- |_ # PERMUTED
0 -> 0
1 -> 3
2 -> 6
3 -> 8
4 -> 1
5 -> 4
6 -> 7
7 -> 9
8 -> 2
9 -> 5
0 -> 0
1 -> 4
2 -> 8
3 -> 1
4 -> 5
5 -> 9
6 -> 2
7 -> 6
8 -> 3
9 -> 7
FINAL SOLUTION
from pwn import *
import sys
def permute(n):
perm = {}
rev = {}
perm[0], rev[0] = 0, 0
perm[1], rev[4] = 4, 1
start = 1
for i in range(2, n):
if perm[i-1] + 4 >= n:
perm[i] = start
rev[start] = i
start += 1
else:
perm[i] = perm[i-1] + 4
rev[perm[i]] = i
def p(s):
x = list(s)
for i, v in enumerate(s):
x[perm[i]] = s[i]
return x
def r(s):
x = list(s)
for i, v in enumerate(s):
x[rev[i]] = s[i]
return x
return p, r
def buildmap(alpha, encoded, n):
maps = {}
for i in range(0, n * int(len(alpha) // n), n):
for j in range(i, i+n):
key = (i + j) % n
if key not in maps:
maps[key] = {}
maps[key][encoded[j]] = alpha[j]
return maps
c = remote("chal.tuctf.com", 30102)
ABC = "abcdefghijklmnopqrstuvwxyz".upper()
alpha = ABC
levels = {
0: (1, False),
1: (1, False),
2: (1, False),
3: (1, False),
4: (1, False),
5: (8, False),
6: (1, True),
7: (1, False),
8: (7, False),
9: (1, True)
}
level = 0
while True:
r = c.readuntil("\n")
if r.startswith("Level"):
level = int(r.strip("\n").split(" ")[1])
lrep, permute = levels[level]
alpha = ''.join([str(i) * lrep for i in ABC])
#if level == 9:
# alpha = 'AB' * 8
if "Give me text:" in r:
c.send(alpha + "\n")
if "encrypted is" in r:
salpha = r.strip("\n").split(" ")[3:]
if permute:
salpha = permute(len(salpha))[0](salpha)
maps = buildmap(alpha, salpha, lrep)
print("LENGTHS: " + str(len(alpha)) + " " + str(len(salpha)))
print("ORIG: " + repr(alpha))
print("NEW ALPHA: " + repr(salpha))
if not r.startswith("Decrypt"):
print('< ' + r)
continue
print("LINE: " + r)
p = r.strip("\n")[8:].split(" ")
o = ""
for i, v in enumerate(p):
o += maps[(i % lrep)][v]
if permute:
o = ''.join(permute(len(o))[0](o))
print("GOT: " + repr(o))
c.send(o + "\n")
c.interactive()